<template>
  <div ref="$editorWrap">
    <button @click="getContents">获取内容</button>
  </div>
  <div class="sw-read-editor">
    <div class="sw-read-editor__content mt-m">
      <div class="sw-read-editor__toolbar">
        <div class="bre-toolbar">
          <FontSize />
          <Bold />
          <Strike />
          <Italic />
          <Color />
          <div class="bre-toolbar__div"></div>
          <Blockquote />
          <CutOff />
          <Align />
          <List />
          <div class="bre-toolbar__div"></div>
          <Link />
          <Image />
          <div title="更多工具" class="tlbr-btn hm">
            <div class="tlbr-btn__icon">
              <svg
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M12.0001 4.91663C8.08806 4.91663 4.91675 8.08794 4.91675 12C4.91675 15.912 8.08806 19.0833 12.0001 19.0833C15.9121 19.0833 19.0834 15.912 19.0834 12C19.0834 8.08794 15.9121 4.91663 12.0001 4.91663ZM3.66675 12C3.66675 7.39758 7.39771 3.66663 12.0001 3.66663C16.6024 3.66663 20.3334 7.39758 20.3334 12C20.3334 16.6023 16.6024 20.3333 12.0001 20.3333C7.39771 20.3333 3.66675 16.6023 3.66675 12Z"
                  fill="currentColor"
                ></path>
                <path
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M12 7.83435C12.3452 7.83435 12.625 8.11418 12.625 8.45935V11.3751H15.5408C15.8859 11.3751 16.1658 11.6549 16.1658 12.0001C16.1658 12.3453 15.8859 12.6251 15.5408 12.6251H12.625V15.5409C12.625 15.886 12.3452 16.1659 12 16.1659C11.6548 16.1659 11.375 15.886 11.375 15.5409V12.6251H8.45923C8.11406 12.6251 7.83423 12.3453 7.83423 12.0001C7.83423 11.6549 8.11406 11.3751 8.45923 11.3751H11.375V8.45935C11.375 8.11418 11.6548 7.83435 12 7.83435Z"
                  fill="currentColor"
                ></path>
              </svg>
            </div>
            <svg
              width="4"
              height="4"
              viewBox="0 0 4 4"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
              class="tlbr-btn__dot"
            >
              <path d="M4 0V4H0L4 0Z" fill="#222222"></path>
            </svg>
            <div class="tlbr-btn__more">
              <div class="tlbr-btn__more__tooltip">
                <ul class="bre-toolbar__optlist more" style="height: 96px">
                  <li title="添加站内视频卡片" class="bre-toolbar__optbtn">
                    <VideoCard />
                  </li>
                  <li title="添加站内文章卡片" class="bre-toolbar__optbtn">
                    <ArticleCard />
                  </li>
                  <li title="添加站内会员购卡片" class="bre-toolbar__optbtn">
                    <MallCard />
                  </li>
                  <li title="添加站内直播卡片" class="bre-toolbar__optbtn">
                    <LiveCard />
                  </li>
                  <li title="添加站内投票卡片" class="bre-toolbar__optbtn">
                    <div class="bre-toolbar__optbtn__lab">投票</div>
                  </li>
                </ul>
              </div>
            </div>
          </div>
          <div
            class="bre-toolbar__savestatus has-tooltip"
            data-original-title="null"
          >
            <div class="bre-toolbar__savestatus__text">未保存</div>
          </div>
          <div title="手机端预览" class="preview tlbr-btn">
            <div class="tlbr-btn__icon">
              <svg
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              >
                <circle cx="12" cy="12" r="12" fill="currentColor"></circle>
                <path
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M9.5 5C8.39543 5 7.5 5.89543 7.5 7V18C7.5 19.1046 8.39543 20 9.5 20H14.5C15.6046 20 16.5 19.1046 16.5 18V7C16.5 5.89543 15.6046 5 14.5 5H9.5ZM9.5 7C8.94772 7 8.5 7.44772 8.5 8V15C8.5 15.5523 8.94772 16 9.5 16H14.5C15.0523 16 15.5 15.5523 15.5 15V8C15.5 7.44772 15.0523 7 14.5 7H9.5ZM13 18C13 18.5523 12.5523 19 12 19C11.4477 19 11 18.5523 11 18C11 17.4477 11.4477 17 12 17C12.5523 17 13 17.4477 13 18ZM10.75 6C10.6119 6 10.5 6.11193 10.5 6.25C10.5 6.38807 10.6119 6.5 10.75 6.5H13.25C13.3881 6.5 13.5 6.38807 13.5 6.25C13.5 6.11193 13.3881 6 13.25 6H10.75Z"
                  fill="white"
                ></path>
              </svg>
            </div>
            <!----><!---->
          </div>
        </div>
      </div>
      <div class="sw-read-editor__input mb-l">
        <div class="sw-read-editor__field">
          <div class="rql-editor ql-container ql-bubble" ref="$editor"></div>
        </div>
        <div class="sw-read-editor__hint">已输入{{ textLength }}字</div>
      </div>
    </div>
  </div>
  <Teleport to="body">
    <div
      id="canvas-wrap"
      class="editor-cards"
      style="position: absolute; top: -9999px; left: -9999px; z-index: -1"
    ></div>
  </Teleport>
</template>
<script setup lang="ts">
import { ref, onMounted, shallowRef, provide } from 'vue'
import 'quill/dist/quill.snow.css'
import Quill, { DeltaOperation, DeltaStatic, RangeStatic } from 'quill'
import FontSize from './toolbar/FontSize/index.vue'
import Bold from './toolbar/Bold/index.vue'
import Strike from './toolbar/Strike/index.vue'
import Italic from './toolbar/Italic/index.vue'
import Color from './toolbar/Color/index.vue'
import Blockquote from './toolbar/Blockquote/index.vue'
import Align from './toolbar/Align/index.vue'
import Image from './toolbar/Image/indev.vue'
import CutOff from './toolbar/CutOff/index.vue'
import List from './toolbar/List/index.vue'
import Link from './toolbar/Link/index.vue'

// 更多
import MallCard from './toolbar/MallCard/index.vue'
import VideoCard from './toolbar/VideoCard/index.vue'
import LiveCard from './toolbar/LiveCard/index.vue'
import ArticleCard from './toolbar/ArticleCard/index.vue'
import { initQuillFormat } from '.'
const Delta = Quill.import('delta')
const $editorWrap = ref<HTMLElement>()
const textLength = ref(0)

const emits = defineEmits<{
  (e: 'update:modelValue', value: DeltaStatic): void
  (e: 'getContent', value: { ops: DeltaOperation[] }): void
}>()
const $editor = ref<HTMLElement>()
const QuillEditor = shallowRef<Quill>()
// 初始化quill事件监听
const initQuillEditor = () => {
  QuillEditor.value?.on('text-change', (delta, oldDelta, source) => {
    // console.log('text-change', delta, oldDelta, source)
    // 更新光标位置
    lastSelectionRange.value =
      QuillEditor.value?.getSelection() || lastSelectionRange.value
    getSelectionFormat()
  })
  QuillEditor.value?.on('selection-change', (range, oldRange, source) => {
    // console.log('selection-change', range, oldRange, source)
    range && (lastSelectionRange.value = range)
    getSelectionFormat()
  })
  QuillEditor.value?.on('editor-change', () => {
    textLength.value = QuillEditor.value?.getText()?.length || 0
  })
}
// 初始化粘贴事件
const initQuillClipboard = () => {
  // 处理粘贴内容，node为节点（根据前面参数），delta为对应类型的操作，可自定义delta，
  // 返回delta
  // 每次粘贴的delta的ops都只包含一个元素，即如果是粘贴两段内容，会触发两次，每次一段内容

  // 例如Node.TEXT_NODE，node为文本节点，delta为文本内容，当粘贴内容包含多种样式时，每一部分的文本都会触发一次
  // [ab加粗][cd删除线][ef斜体] 会触发三次，分别是[ab]、[cd]、[ef]，如果是嵌套，则再继续分割
  // 它是按照类型触发的
  // QuillEditor.value?.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => {
  //   return delta
  // })

  // Node.ELEMENT_NODE 则以节点为整体触发，此时会包含attributes，而Node.TEXT_NODE则以文本为触发，此时只包含insert
  QuillEditor.value?.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
    // console.log(node)
    // 拦截所有文字颜色
    delta.ops?.forEach((op) => {
      if (op.attributes?.color) {
        op.attributes.color = false
      }
      if (op.attributes?.link) {
        // 当在浏览器导航栏复制链接，粘贴会变成link，此时需要拦截
        // 判断链接是否为本站链接
      }
      if (op?.insert?.image) {
        // op.insert.image = false
        // 这种方式只支持粘贴base64图片
        op.insert = {
          'native-image': {
            src: op.insert.image,
          },
        }
        op.attributes = {
          class: 'normal-img',
        }
      }
    })
    return delta
  })
}

const getSelectionFormat = () => {
  const range = QuillEditor.value?.getSelection() || lastSelectionRange.value
  if (range) {
    formatMap.value = QuillEditor.value?.getFormat(range.index) || {}
  } else {
    formatMap.value = {}
  }
}

const getContents = () => {
  const contents = QuillEditor.value?.getContents() || new Delta()
  console.log('contents', contents)
  emits('update:modelValue', contents)
  emits('getContent', contents)
}

const lastSelectionRange = ref<RangeStatic>()
const formatMap = ref<Record<string, any>>({})

onMounted(() => {
  if ($editor.value) {
    QuillEditor.value = new Quill($editor.value, {
      placeholder: '请输入正文',
      modules: {
        toolbar: false,
      },
      readOnly: false,
    })
    initQuillEditor()
    initQuillFormat(QuillEditor)
    initQuillClipboard()
    QuillEditor.value.insertText(0, '专栏', {})
    QuillEditor.value.insertEmbed(3, 'article-card', { id: 'cv10555126' })
    QuillEditor.value.insertText(4, '视频', {})
    QuillEditor.value.insertEmbed(7, 'video-card', { id: 'BV1M453zvEr9' })
    QuillEditor.value.insertText(8, '直播', {})
    QuillEditor.value.insertEmbed(11, 'live-card', { id: 'lv22478506' })
    QuillEditor.value.insertText(12, '会员购', {})
    QuillEditor.value.insertEmbed(16, 'mall-card', { id: 'pw10252560' })
    QuillEditor.value.insertText(17, '\n')
  }
})
provide('QuillEditor', QuillEditor)
provide('lastSelectionRange', lastSelectionRange)
provide('formatMap', formatMap)
provide('getSelectionFormat', getSelectionFormat)
provide('$editorWrap', $editorWrap)

const handleClick = (e: MouseEvent) => {
  const focusedList = document.querySelectorAll('.focused')
  if (focusedList?.length) {
    Array.from(focusedList).forEach((item) => {
      item.classList.remove('focused')
    })
  }
  const target = e.target as HTMLElement
  if (
    target.classList.contains('normal-img') ||
    target.classList.contains('card')
  ) {
    target.classList.add('focused')
  }
}
document.addEventListener('click', handleClick)
</script>
<style lang="scss">
@use './styles.scss' as rql;
@use './article.scss' as article;
</style>
